package com.thermofisher.dsc.amanda.auth.service.impl;

import com.thermofisher.dsc.amanda.auth.mapper.UserMapper;
import com.thermofisher.dsc.amanda.auth.service.EmailPasswdService;
import com.thermofisher.dsc.amanda.model.po.auth.User;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

/**
 * Created by ling.fan2 on 1/25/2019.
 */
@Service
@Slf4j
@EnableScheduling
public class EamilPasswdServiceImpl implements EmailPasswdService {

  @Autowired
  private UserMapper userMapper;

  @Autowired
  private PasswordEncoder passwordEncoder;

  @Value("${email.server.host}")
  private String serverHost;

  @Value("${email.server.port}")
  private String serverPort;

  @Value("${email.server.account}")
  private String account;

  @Value("${email.server.password}")
  private String password;

  //fixme when deploy on cloud will enable
  @Override
//  @Scheduled(fixedDelay = 1000 * 60 * 60 * 24, initialDelay = 1)
  public String emailInitPass() {
    List<User> noPasswdUsers = userMapper.getNoPasswdUsers();
    Session session = initEmailSession(noPasswdUsers);
    if (session == null) {
      return "success";
    }
    final Transport transport;
    try {
      transport = session.getTransport();
      transport.connect(account, password);
      noPasswdUsers.forEach(user -> {
        sendPasswdMessage(session, transport, user);
      });
      transport.close();
    } catch (NoSuchProviderException e) {
      log.error("no such provider", e);
    } catch (MessagingException e) {
      log.error("message exception", e);
    }

    return "success";
  }


  private void sendPasswdMessage(Session session, Transport transport, User user) {
    String email = user.emailAddress;
    if (!Strings.isBlank(email)) {
      try {
        Long id = user.getId();
        String passwd = generatePasswd();
        String encodedPasswd = passwordEncoder.encode(passwd);
        MimeMessage message = getMimeMessage(session, email, passwd);
        transport.sendMessage(message, message.getAllRecipients());
        userMapper.updateNoPasswdUser(id, encodedPasswd);
      } catch (MessagingException e) {
        log.error("message exception", e);
      } catch (UnsupportedEncodingException e) {
        log.error("unsupport encoding", e);
      }

    }
  }

  private MimeMessage getMimeMessage(Session session, String email, String passwd)
      throws MessagingException, UnsupportedEncodingException {
    MimeMessage message = new MimeMessage(session);
    final String charset = "UTF-8";
    message.setFrom(new InternetAddress(account, "biologic profile", charset));
    message.setRecipient(MimeMessage.RecipientType.TO,
        new InternetAddress(email, "biologic profile user", charset));
    message.setSubject("bioligc profile test", charset);
    message.setContent("your biologic profile username:" + email + "\npassword:" + passwd,
        "text/html;charset=UTF-8");
    message.setSentDate(new Date());
    message.saveChanges();
    return message;
  }

  private Session initEmailSession(List<User> noPasswdUsers) {
    if (noPasswdUsers == null || noPasswdUsers.size() == 0) {
      return null;
    }
    Session session = Session.getInstance(getEmailProperty(), new javax.mail.Authenticator() {
      @Override
      protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(account, password);
      }
    });
    session.setDebug(true);
    return session;
  }


  private Properties getEmailProperty() {
    Properties props = new Properties();
    props.setProperty("mail.transport.protocol", "smtp");
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.ssl.checkserveridentity", "false");
    props.put("mail.smtp.ssl.trust", serverHost);
    props.put("mail.smtp.host", serverHost);
    props.put("mail.smtp.port", serverPort);
    return props;
  }

  private String generatePasswd() {
    int randomStrLength = 8;
    char[] possibleCharacters = (new String(
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*-_=+\\|;:\'\",<.>/?"))
        .toCharArray();
    return RandomStringUtils
        .random(randomStrLength, 0, possibleCharacters.length - 1, false, false, possibleCharacters,
            new SecureRandom());
  }

}
